home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
copascal.arc
/
COPASCAL.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1986-06-18
|
15KB
|
537 lines
(*
The * Co-Pascal * COMPILER
...is a modified version of the PASCAL-S compiler to permit
interleaved concurrent program execution. The reserved words
"COBEGIN" and "COEND" mark concurrent blocks while calls to
the predefined functions WAIT and SIGNAL provide synchronization.
The changes are from "Principles of Concurrent Programming by
BEN-ARI.
The defining document for PASCAL-S is:
PASCAL-S: A SUBSET AND ITS IMPLEMENTATION by N. WIRTH.
HISTORY:
. PASCAL-S developed by N. Wirth, 1976.
. PASCAL-S modified for the HP/3000 by D. Greer.
. M. Ben-Ari develops additions to the Pascal language to provide
for simulated concurrency. See Ben-Ari : 'Principles of Concurrent
Programming. Pretice-Hall, 1982.
. B. Burd incorporates Ben-Ari's changes into PASCAL-S,
developing CO-PASCAL for the VAX/11-750 under VMS, 1985.
. C. Schoening modifies and enhances CO-PASCAL for Turbo-Pascal v2.0
under CP/M and MS-DOS, 1985.
*)
program Co_Pascal( INPUT, OUTPUT );
{$R+}
{$I HEADER.MOD }
(*------------------------------------------------------COMPILE-----*)
overlay procedure compile;
const KEY : array[1..NKW] of string[10] =
( 'AND ', 'ARRAY ',
'BEGIN ', 'CASE ',
'COBEGIN ', 'COEND ',
'CONST ', 'DIV ',
'DO ', 'DOWNTO ',
'ELSE ', 'END ',
'FOR ', 'FUNCTION ',
'IF ', 'MOD ',
'NOT ', 'OF ',
'OR ', 'PROCEDURE ',
'PROGRAM ', 'RECORD ',
'REPEAT ', 'THEN ',
'TO ', 'TYPE ',
'UNTIL ', 'VAR ',
'WHILE ' );
type SYMBOL = ( INTCON, REALCON, CHARCON, WORD,
PLUS, MINUS, TIMES, IDIV, RDIV, IMOD,
NOTSY, ANDSY, ORSY,
EQL, NEQ, GTR, GEQ, LSS, LEQ,
LPARENT, RPARENT, LBRACK, RBRACK,
COMMA, SEMICOLON, PERIOD, COLON,
BECOMES, CONSTSY, TYPESY, VARSY, ARRAYSY, RECORDSY,
FUNCSY, PROCSY, PROGRAMSY, IDENT, BEGINSY, ENDSY,
REPEATSY, UNTILSY, WHILESY, DOSY, FORSY,
IFSY, THENSY, ELSESY, CASESY, OFSY, TOSY, DOWNTOSY );
SYMSET = SET OF SYMBOL;
const KSY : array[1..NKW] of SYMBOL =
( ANDSY, ARRAYSY, BEGINSY, CASESY,
BEGINSY, ENDSY, CONSTSY, IDIV,
DOSY, DOWNTOSY, ELSESY, ENDSY,
FORSY, FUNCSY, IFSY, IMOD,
NOTSY, OFSY, ORSY, PROCSY,
PROGRAMSY, RECORDSY, REPEATSY, THENSY,
TOSY, TYPESY, UNTILSY, VARSY,
WHILESY );
var DISPLAY : ARRAY [ 0 .. LMAX ] of INTEGER;
SPS : ARRAY [ ' '.. ']' ] of SYMBOL;
(*
=============================
key words and special symbols
=============================
*)
(* indicies to tables *)
T, (* ---> TAB, *)
A, (* ---> ATAB, *)
SX, (* ---> STAB, *)
C1, (* ---> RCONST, *)
C2, (* ---> RCONST *)
LC (* program Location Counter *) : INTEGER;
(*
=========================
Error Control Variables
=========================
*)
ERRS : SET OF 0..ERMAX; (* compilation errors *)
ERRPOS : INTEGER;
SKIPFLAG : BOOLEAN; (* used by procedure ENDSKIP *)
(*
=============================
Insymbol (scanner) Variables
=============================
*)
SY : SYMBOL; (* last symbol read by INSYMBOL *)
ID : ALFA; (* identifier from INSYMBOL *)
INUM : INTEGER; (* integer from INSYMBOL *)
RNUM : REAL; (* real number from INSYMBOL *)
SLENG : INTEGER; (* string length *)
CHARTP: ARRAY[CHAR] OF CHTP; (* character types *)
LINE : ARRAY [1..LLNG] OF CHAR; (* input line *)
CC : INTEGER; (* character counter *)
LL : INTEGER; (* length of current line *)
LINECOUNT: INTEGER; (* source line counter *)
(*
======
sets
======
*)
CONSTBEGSYS, TYPEBEGSYS,
BLOCKBEGSYS, FACBEGSYS, STATBEGSYS : SYMSET;
(*--------------------------------------------------------ERROR-----*)
procedure ERROR( N : INTEGER );
(*
write error on current line & add to TOT ERR
*)
begin
if ERRPOS = 0 then write('[**> ', ' ':6);
if CC > ERRPOS then begin
write( ' ': CC-ERRPOS, '^', N:2 );
ERRPOS := CC+3;
ERRS := ERRS + [N];
end;
end; { ERROR }
(*-----------------------------------------------------ENDSKIP------
ENDSKIP changed to just print blanks for skipped symbols.
This should cause less confusion than the underlining did.
*)
procedure ENDSKIP; (* underline skipped part of input *)
begin
while ERRPOS < CC do begin
write(' ');
ERRPOS := ERRPOS + 1;
end;
SKIPFLAG := FALSE;
end; { ENDSKIP }
procedure FATAL( N : integer ); forward;
procedure NEXTCH; forward;
(*---------------------------------------------------------EMIT-----
emit actual code into the code table
*)
procedure EMIT(FCT: INTEGER);
begin
if LC = CMAX then FATAL(6);
CODE[LC].F := FCT;
LC := LC+1;
end; { EMIT }
procedure EMIT1(FCT,B: INTEGER);
begin
if LC = CMAX then FATAL(6);
with CODE[LC] do begin
F := FCT;
Y := B;
end;
LC := LC+1;
end; { EMIT1 }
procedure EMIT2(FCT,A,B: INTEGER);
begin
if LC = CMAX then FATAL(6);
with CODE[LC] do begin
F := FCT;
X := A;
Y := B;
end;
LC := LC+1;
end; { EMIT2 }
(*-----------------------INITTABLES----ERRORMSG----ENTERSTDFCNS-----*)
{$I INIT.MOD }
(*-----------------------------------------------------INSYMBOL-----*)
{$I INSYMBOL.MOD }
(*--------------------------------------------------PRINTTABLES-----
this procedure prints out the internal compiler and
interpreter tables. This procedure is called if the
DEBUG flag is TRUE.
*)
procedure PRINTTABLES;
var I: INTEGER;
O: ORDER;
begin
writeln;
writeln(' Identifiers Link Obj Typ Ref NRM Lev Adr');
for I := BTAB[1].LAST +1 to T do with TAB[I] do
writeln(I,' ',NAME,LINK:5, ORD(OBJ):5, ORD(TYP):5, REF:5,
ORD(NORMAL):5, LEV:5, ADR:5);
writeln(' Blocks Last LPar PSze Vsze');
for I := 1 to B do with BTAB[I] do
writeln(I, LAST:5, LASTPAR:5, PSIZE:5, VSIZE:5);
writeln;
writeln(' Arrays Xtyp Etyp Eref Low High Elsz Size');
for I := 1 to A do with ATAB[I] do
writeln(I, ORD(INXTYP):5, ORD(ELTYP):5,
ELREF:5, LOW:5, HIGH:5, ELSIZE:5, SIZE:5);
writeln(' CODE:');
for I := 0 to LC-1 do begin
if I MOD 5 = 0 then begin
writeln; write(I:5)
end;
O := CODE[I];
write(O.F:5);
if O.F < 31 then
if O.F < 4 then write(O.X:2, O.Y:5)
else write(O.Y:7)
else write(' ');
write(',');
end;
writeln;
end; { PRINTTABLES }
(*--------------------------------------------------------BLOCK-----*)
{$I BLOCKA.MOD }
{$I BLOCKB.MOD }
{$I BLOCKC.MOD }
(*--------------------------------------------------------FATAL-----*)
procedure FATAL; (* internal table overflow *)
begin
if ERRS <> [] then ERRORMSG;
writeln;
write( 'COMPILER TABLE for ' );
case N of
1 : write( 'IDENTIFIER' );
2 : write( 'PROCEDURES' );
3 : write( 'REALS' );
4 : write( 'ARRAYS' );
5 : write( 'LEVELS' );
6 : write( 'CODE' );
7 : write( 'STRINGS' );
end;
writeln( ' is too SMALL' );
writeln;
writeln(' Please take this output to the maintainer of ');
writeln(' this language for your installation ' );
writeln; writeln;
writeln(' FATAL termination of Co-Pascal');
HALT;
end; { FATAL }
(*-------------------------------------------------------NEXTCH-----*)
procedure NEXTCH; (* read next char; process line end *)
begin
if CC = LL then begin
if EOF( SOURCE ) then begin
writeln;
writeln(' PROGRAM INCOMPLETE');
ERRORMSG;
HALT;
end;
if ERRPOS <> 0 then begin
if SKIPFLAG then endSKIP;
ERRPOS := 0;
writeln;
end;
LINECOUNT := LINECOUNT + 1;
write( LINECOUNT:4,' ' );
write( LC:5, ' ' );
LL := 0;
CC := 0;
while NOT EOLN(SOURCE) do begin
LL := LL+1;
read( SOURCE,CH);
write(CH);
LINE[LL] := CH
end;
LL := LL + 1;
writeln;
readln( SOURCE );
LINE[LL] := ' ';
end;
CC := CC+1;
CH := LINE[CC];
if (ORD(CH) < ORD(' ')) then ERROR(60)
end; { NEXTCH }
begin { COMPILE }
(*
=============================
check for program heading
=============================
*)
INITIALIZE;
INSYMBOL;
if SY <> PROGRAMSY then ERROR(3) else begin
INSYMBOL;
if SY <> IDENT then ERROR(2) else begin
PROGNAME := ID;
INSYMBOL;
if SY <> LPARENT then ERROR(9) else repeat
INSYMBOL;
if SY <> IDENT then ERROR(2) else begin
if ID = 'INPUT ' then IFLAG := TRUE
else if ID = 'OUTPUT ' then OFLAG := TRUE
else if ( NOT DFLAG ) then begin
DFILE := ' ';
M := 0;
while ID[m+1] in [ 'A'..'Z', '0'..'9', ':' ]
do M := M + 1;
MOVE( ID, DFILE[11-m], m );
DFLAG := TRUE;
writeln( ' DFLAG <- TRUE ', DFILE, m:5 );
end else ERROR(0);
INSYMBOL;
end;
until SY <> COMMA;
if SY = RPARENT then INSYMBOL else ERROR(4);
if NOT OFLAG then ERROR(20)
end
end;
ENTERSTDFCNS;
with BTAB[1] do begin
LAST := T;
LASTPAR := 1;
PSIZE := 0;
VSIZE := 0
end;
(*
============
COMPILE
============
*)
block( BLOCKBEGSYS+STATBEGSYS, FALSE, 1 );
if (SY <> PERIOD) then ERROR(22);
EMIT(31); (* halt *)
if ( BTAB[2].VSIZE > STMAX-STKINCR * PMAX ) then ERROR(49);
if DEBUG then PRINTTABLES;
if ERRS <> [] then begin
ERRORMSG;
HALT;
end;
end; { COMPILE }
(*----------------------------------------------------INTERPRET------*)
overlay procedure INTERPRET;
{$I INTERPT.MOD }
end; { INTERPRET }
(*---------------------------------------------------P_CODE I/O-----*)
procedure PutBlock( FileName : FNAME );
var ObjFile : file;
t : string[ 3];
len : integer;
begin
assign( ObjFile, FileName + '.OBJ' );
rewrite( ObjFile );
for len := 1 to 25 do SS[len] := ' ';
len := length( SFILE );
MOVE( SFILE[1], SS[11-len], len );
if DFLAG then MOVE( DFILE[1], SS[11], 10 );
MOVE( IFLAG, SS[21], 1 );
MOVE( OFLAG, SS[22], 1 );
MOVE( DFLAG, SS[23], 1 );
MOVE( B , SS[24], 2 );
blockwrite( ObjFile, TAB, ( SizeOf( TAB) DIV 128 )+1 );
blockwrite( ObjFile, ATAB, ( SizeOf( ATAB) DIV 128 )+1 );
blockwrite( ObjFile, BTAB, ( SizeOf( BTAB) DIV 128 )+1 );
blockwrite( ObjFile, STAB, ( SizeOf( STAB) DIV 128 )+1 );
blockwrite( ObjFile, CODE, ( SizeOf( CODE) DIV 128 )+1 );
blockwrite( ObjFile, RCONST, ( SizeOf(RCONST) DIV 128 )+1 );
blockwrite( ObjFile, SS, ( SizeOf( SS) DIV 128 )+1 );
close( ObjFile );
end;
procedure GetBlock( FileName : FNAME );
type temptr = ^tempdat;
tempdat = array [1..128] of 0..255;
var ObjFile : file;
a : temptr;
temp : tempdat;
len : integer;
procedure B_read( var varname; q : integer );
begin
blockread( ObjFile, varname, ( Q DIV 128 ) );
blockread( ObjFile, temp, 1 );
a := ptr( Seg(varname), Ofs(varname) + 128*( Q DIV 128 ) );
move( temp, a^, ( Q MOD 128 ) );
end;
begin
assign( ObjFile, FileName + '.OBJ' );
reset( ObjFile );
B_read( TAB, SizeOf( TAB ));
B_read( ATAB, SizeOf( ATAB ));
B_read( BTAB, SizeOf( BTAB ));
B_read( STAB, SizeOf( STAB ));
B_read( CODE, SizeOf( CODE ));
B_read( RCONST, SizeOf( RCONST ));
B_read( SS, SizeOf( SS ));
len := 1;
while SFILE[len] = ' ' do len := len+1;
MOVE( SS[len], SFILE[1],10 ); SFILE[0] := CHR( 11-len );
MOVE( SS[ 21], IFLAG, 1 );
MOVE( SS[ 22], OFLAG, 1 );
MOVE( SS[ 23], DFLAG, 1 );
MOVE( SS[ 24], B, 2 );
if DFLAG then MOVE( SS[11], DFILE[1], 10 ); DFILE[0] := CHR(10);
if DEBUG then begin
writeln;
write(' S: ',SFILE+'.PAS ');
if DFLAG then writeln('D: ',DFILE+'.DAT' ) else writeln;
writeln(' flags I/O/D :',IFLAG:8,OFLAG:6,DFLAG:6,' B : ',B );
writeln;
end;
end;
procedure HELP;
begin
writeln;
writeln(' Selection error. Correct syntax is : FNAME -X* ');
writeln;
writeln(' where FNAME is a legal file name with the .TYP optional ');
writeln(' and the <X> option is one of the following : ');
writeln;
writeln(' C :: compile the source code to P-code ');
writeln(' E :: execute a previously compiled P-code ');
writeln(' R :: compile and then execute ');
writeln;
writeln(' * is an optional flag to display debug information ');
writeln;
halt;
end;
begin { MAIN }
if ( ParamCount < 1 ) then HELP;
SFILE := ParamStr(1);
for m := 1 to length( SFILE ) do SFILE[m] := UpCase( SFILE[m] );
assign( SOURCE, SFILE+'.PAS' );
{$I-}
reset( SOURCE )
{$I+};
if IOresult <> 0 then begin
writeln('Cannot find file : ', SFILE+'.PAS' );
halt;
end;
writeln; writeln(' ':10,HEADER); writeln;
if ( ParamCount < 2 ) then begin
OPTION := 'R';
DEBUG := FALSE;
end else begin
CmdLine := ParamStr(2);
if ( CmdLine[1] = '-' ) then OPTION := UpCase( CmdLine[2] ) else HELP;
if ( CmdLine[3] = '*' ) then DEBUG := TRUE else DEBUG := FALSE;
end;
case OPTION of
'C' : begin
COMPILE;
PutBlock( SFILE );
end;
'E' : begin
GetBlock( SFILE );
INTERPRET;
end;
'R' : begin
COMPILE;
writeln;
writeln(' begin execution for : ', PROGNAME );
writeln;
INTERPRET;
end;
else HELP;
end;
writeln;
end.